package com.herench.router;


import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxws.JaxWsServerFactoryBean;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.apache.log4j.Logger;

import java.io.InputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class RouterService {


    /**
     * 定义日志记录工具类，日志写入方式为异步
     */
    private static final Logger logger = Logger.getLogger(RouterService.class);

    /**
     * 定义路由存储map，需要线程安全
     */
    private static Map<String, RouterMapping> mappingMap = new ConcurrentHashMap<>();

    private static String defaultUrl;
    /**
     * 定义webservice代理实现接口
     */
    private static WsProxy supplier;
    /**
     * 定义web容器成员变量
     */
    private static Server server;
    /**
     * 定义对外访问URL地址
     */
    private static String serverUrl;

    public Map<String, RouterMapping> getMappingMap() {
        return mappingMap;
    }

    public void setMappingMap(Map<String, RouterMapping> mappingMap) {
        this.mappingMap = mappingMap;
    }


    /**
     * 初始化方法
     */
    public void init() {
        /**
         * 读取resource下的router-config.xml 文件，读取方式为流式读取
         */
        InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("router-config.xml");
        try {
            /**
             * 转化成dom
             */
            Document document = new SAXReader().read(is);
            /**
             * 读取对外暴露的访问地址
             */
            serverUrl = document.getRootElement().elementText("server-url");

            /**
             * 开始接续配置文件中的mappers节点
             */
            Element mapperConfigElement = document.getRootElement().element("mapper-config");
            defaultUrl = mapperConfigElement.elementText("default-url");

            Element mappers = mapperConfigElement.element("mappers");
            if (mappers != null) {
                for (Iterator<Element> iterator = mappers.elementIterator(); iterator.hasNext(); ) {
                    Element mapperEl = iterator.next();
                    RouterMapping routerMapping = new RouterMapping(mapperEl.elementText("method"), mapperEl.elementText("target-method"), mapperEl.elementText("target-url"));
                    mappingMap.put(routerMapping.getMethod(), routerMapping);
                }
            }
            /**
             * 结束mappers解析
             */
        } catch (DocumentException e) {
            e.printStackTrace();
        }

        /**
         * 定义动态代理服务创建工厂类对象
         */
        JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
        /**
         * 初始化服务模板，模板使用接口内部实现内方式，以精简结构
         */
        supplier = new WsProxy<String>() {
            @Override
            public String send(final String originalMessage) {
                String result = "";
                logger.info("originalMessage:" + originalMessage);
                try {
                    Document document = DocumentHelper.parseText(originalMessage);
                    Element clientInfo = document.getRootElement().element("ClientInfo").element("Info");
                    String method = clientInfo.attributeValue("METHOD");
                    RouterMapping routerMapping = mappingMap.get(method);
                    if (routerMapping == null) {
                        throw new RuntimeException("未找到对应的url,注意核对配置是否正确.");
                    } else {
                        Client client = WsClientFactory.getInstance().getWsClient(routerMapping.getTargetUrl());
                        Object[] res = client.invoke(routerMapping.getTargetMethod(), originalMessage);
                        logger.info("resMessage:" + res[0]);
                        result = (String) res[0];
                    }
                } catch (Exception e) {
                    logger.info("exception:" + e.getMessage());
                    e.printStackTrace();
                    result = e.getMessage() != null ? e.getMessage() : "空指针异常";
                }
                return result;
            }
        };
        factory.setServiceClass(WsProxy.class);
        factory.setAddress(serverUrl);
        factory.setServiceBean(supplier);
        this.server = factory.create();

    }

    public static void main(String[] args) {
        RouterService service = new RouterService();
        service.init();
    }


    /**
     * 定义路由存储内部类
     */
    class RouterMapping {

        /**
         * 报文中的方法属性
         */
        private String method;
        /**
         * 目的调用方法名
         */
        private String targetMethod;
        /**
         * 目的调用wsdl
         */
        private String targetUrl;


        /**
         * 创建 三参数构造方法，以精简代码
         *
         * @param method
         * @param targetMethod
         * @param targetUrl
         */
        public RouterMapping(String method, String targetMethod, String targetUrl) {
            this.method = method;
            this.targetMethod = targetMethod;
            this.targetUrl = targetUrl;
            if (StringUtils.isEmpty(this.targetUrl)) {
                this.targetUrl = defaultUrl;
            }
        }

        public String getMethod() {
            return method;
        }

        public void setMethod(String method) {
            this.method = method;
        }

        public String getTargetMethod() {
            return targetMethod;
        }

        public void setTargetMethod(String targetMethod) {
            this.targetMethod = targetMethod;
        }

        public String getTargetUrl() {
            return targetUrl;
        }

        public void setTargetUrl(String targetUrl) {
            this.targetUrl = targetUrl;
        }
    }

}
